﻿using System;

using SharpGL.SceneGraph.Effects;

namespace SharpGL.SceneGraph
{
    /// <summary>
    /// The SceneTreeChangeAction enumeration is used
    /// to identify what kind of change is occuring
    /// in scene tree.
    /// </summary>
    public enum SceneTreeChangeAction
    {
        /// <summary>
        /// New element is added in scene tree.
        /// </summary>
        AddElement,

        /// <summary>
        /// Element is removed from scene tree.
        /// </summary>
        RemoveElement,

        /// <summary>
        /// New effect is added to scene element.
        /// </summary>
        AddEffect,

        /// <summary>
        /// Effect is removed from scene element.
        /// </summary>
        RemoveEffect
    }

    /// <summary>
    /// The SceneTreeChangeEventArgs class.
    /// </summary>
    public class SceneTreeChangeEventArgs : EventArgs
    {
        #region Private Fields

        private SceneTreeChangeAction action;
        private SceneElement sceneElement = null;
        private Effect effect = null;

        #endregion Private Fields

        #region Constructors

        public SceneTreeChangeEventArgs(SceneTreeChangeAction action, SceneElement sceneElement)
        {
            if (action != SceneTreeChangeAction.AddElement &&
                action != SceneTreeChangeAction.RemoveElement)
                throw new ArgumentException("Must be AddElement or RemoveElement.", "action");

            if (sceneElement == null)
                throw new ArgumentNullException("sceneElement");

            this.action = action;
            this.sceneElement = sceneElement;
        }

        public SceneTreeChangeEventArgs(SceneTreeChangeAction action, Effect effect)
        {
            if (action != SceneTreeChangeAction.AddEffect &&
                action != SceneTreeChangeAction.RemoveEffect)
                throw new ArgumentException("Must be AddEffect or RemoveEffect.", "action");

            if (effect == null)
                throw new ArgumentNullException("effect");

            this.action = action;
            this.effect = effect;
        }

        #endregion Constructors

        #region Public Properties

        public SceneTreeChangeAction Action
        {
            get { return action; }
            protected set { action = value; }
        }

        public Effect Effect
        {
            get { return effect; }
            protected set { effect = value; }
        }

        public SceneElement SceneElement
        {
            get { return sceneElement; }
            protected set { sceneElement = value; }
        }
        
        #endregion Public Properties
    }

    /// <summary>
    /// Represents the method that will handle change
    /// event of a scene tree.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">A ContextChangeEventArgs that contains the event data.</param>
    public delegate void SceneTreeChangeEventHandler(object sender, SceneTreeChangeEventArgs e);
}
